#include "qcompletertreewidget.h"

#include "qhostobjectmap.h"

#include <QHeaderView>
#include <QTreeWidgetItem>
#include <QFontMetrics>
#include <QItemDelegate>
#include <QPainter>
#include <QScrollBar>
#include <QKeyEvent>
#include <QStringList>



using namespace CORELIB;

#define FONT_SIZE 9

namespace CORELIB
{

    class QCompleterDelegate: public QItemDelegate
    {
    public :
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
    };

}

void QCompleterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV3 opt=option;
    QColor c;
    c=QColor(255,230,151);
    if(opt.features & QStyleOptionViewItemV2::Alternate)
    {
        c=c.lighter(130);
    }

    painter->fillRect(option.rect,c);
    opt.state &=~ QStyle::State_HasFocus;
    opt.font.setPointSize(FONT_SIZE);
    QItemDelegate::paint(painter,opt,index);
}

QSize QCompleterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize sz=QItemDelegate::sizeHint(option,index);
    sz.setHeight(20);
    return sz;
}

QCompleterTreeWidget::QCompleterTreeWidget(QWidget *parent) :
    QTreeWidget(parent)
{
    this->setCursor(QCursor(Qt::ArrowCursor));
    this->header()->hide();
    this->setRootIsDecorated(false);
    this->setAlternatingRowColors(true);
    this->setFocusProxy((QWidget*)parent->parent());
    this->setItemDelegate(new QCompleterDelegate);
    this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setSelectionBehavior(QAbstractItemView::SelectRows);
    this->setSelectionMode(QAbstractItemView::SingleSelection);
    this->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    QFont f=this->font();
    f.setPointSize(FONT_SIZE);
    parent->parent()->installEventFilter(this);

    connect(this,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(itemselect(QTreeWidgetItem*,int)));
}

void QCompleterTreeWidget::insertInfo(QList<tagObjectInfo *> list)
{
    this->clear();
    m_items.clear();
    foreach(tagObjectInfo* info,list)
    {
        QTreeWidgetItem *item=new QTreeWidgetItem(this);
        item->setText(0,info->m_name);
        item->setToolTip(0,info->m_name);
        if(info->m_children.size()>0)
        {
            item->setIcon(0,QIcon(":/images/uniform.png"));
        }
        else
        {
            item->setIcon(0,QIcon(":/images/var.png"));
        }
        if(this->model()->rowCount()==1)
        {
            setCurrentItem(item);
        }
        m_items.insert(item,info);
    }
}

void QCompleterTreeWidget::move_position(const QRect &re)
{
    int width=parentWidget()->width();
    int height=parentWidget()->height();

    int h = (this->sizeHintForRow(0) * qMin(10, this->model()->rowCount()));
    int w=this->sizeHintForColumn(0);
    if(model()->rowCount()>10)
    {
        w+=20;
    }
    else
    {
        w+=4;
    }


    int x,y;
    x=re.left();
    y=re.bottom();
    if(width<re.left()+w)
    {
        x=width-w;
    }
    if(height<re.bottom()+h)
    {
        y=re.top()-h;
    }

    this->setGeometry(x,y,w,h+2);
}

bool QCompleterTreeWidget::eventFilter(QObject *o, QEvent *e)
{
    if(!this->isVisible())
    {
        return false;
    }

    if (o != parent()->parent())
        return QObject::eventFilter(o, e);

    switch (e->type()) {
    case QEvent::KeyPress: {
        QKeyEvent *ke = static_cast<QKeyEvent *>(e);

        QModelIndex curIndex = this->currentIndex();
        QModelIndexList selList = this->selectionModel()->selectedIndexes();

        const int key = ke->key();
        if ((key == Qt::Key_Up || key == Qt::Key_Down) && selList.isEmpty() && curIndex.isValid()) {
              setCurrentIndex(curIndex);
              return true;
        }
        if(ke->text()==".")
        {
            if(curIndex.isValid())
            {
                QTreeWidgetItem *item=itemFromIndex(curIndex);
                tagObjectInfo *info=m_items.value(item);
                if(info->m_children.size()>0)
                {
                    hide();
                    select(info);
                }
            }
            return true;
        }
        switch (key) {
        case Qt::Key_End:
            if (ke->modifiers() & Qt::ControlModifier)
            {
                return false;
            }
            else
            {
                QModelIndex lastIndex = model()->index(model()->rowCount() - 1,0);
                setCurrentIndex(lastIndex);
                return true;
            }
        case Qt::Key_Home:
            if (ke->modifiers() & Qt::ControlModifier)
            {
                return false;
            }
            else
            {
                QModelIndex firstIndex = model()->index(0, 0);
                setCurrentIndex(firstIndex);
                return true;
            }
        case Qt::Key_Up:
            if (!curIndex.isValid()) {
                int rowCount = this->model()->rowCount();
                QModelIndex lastIndex = model()->index(rowCount - 1,0);
                setCurrentIndex(lastIndex);
                return true;
            } else if (curIndex.row() == 0) {
                setCurrentIndex(QModelIndex());
                return true;
            }
            else
            {
                QModelIndex c = model()->index(curIndex.row() - 1,0);
                setCurrentIndex(c);
                return true;
            }
        case Qt::Key_Down:
            if (!curIndex.isValid()) {
                QModelIndex firstIndex = model()->index(0, 0);
                setCurrentIndex(firstIndex);
                return true;
            } else if (curIndex.row() == model()->rowCount() - 1) {
                setCurrentIndex(QModelIndex());
                return true;
            }
            else
            {
                QModelIndex c = model()->index(curIndex.row() + 1,0);
                setCurrentIndex(c);
                return true;
            }

        case Qt::Key_PageUp:
        case Qt::Key_PageDown:
            return false;
        }

        switch (key)
        {
        case Qt::Key_Return:
        case Qt::Key_Enter:
        case Qt::Key_Tab:
            hide();
            if (curIndex.isValid())
            {
                QTreeWidgetItem *item=this->itemFromIndex(curIndex);
                emit select(m_items.value(item));
            }
            return true;
        case Qt::Key_Backtab:
        case Qt::Key_Escape:
            hide();
            return true;
        default:
            return false;
        }
    }
    default:
        return false;
    }
    return false;
}

void QCompleterTreeWidget::itemselect(QTreeWidgetItem *item, int)
{
    hide();
    emit select(m_items.value(item));
}
